#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
提示词优化器模块

该模块负责对生成的提示词进行优化，提高提示词的质量和有效性。
"""

import logging
import re
from typing import Dict, List, Optional

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class PromptOptimizer:
    """
    提示词优化器类
    
    负责对生成的提示词进行各种优化，包括长度调整、清晰度提升、冗余去除等。
    """
    
    def __init__(self):
        """
        初始化提示词优化器
        
        设置优化参数和规则
        """
        # 优化参数配置
        self.max_prompt_length = 1500  # 最大提示词长度
        self.min_prompt_length = 50    # 最小提示词长度
        self.keyword_weight_factor = 1.2  # 关键词权重因子
        
        # 常见冗余短语列表
        self.redundant_phrases = [
            '需要注意的是',
            '值得一提的是',
            '实际上',
            '事实上',
            '基本上',
            '总的来说',
            '也就是说',
            '换句话说',
            '可以这么说',
            '从某种意义上讲'
        ]
        
        # 编码类目相关的关键词
        self.category_keywords = {
            'scene_setting': ['场景', '环境', '地点', '背景', '空间'],
            'theme_type': ['主题', '核心', '中心思想', '主旨', '重点'],
            'emotional_tendency': ['情感', '情绪', '倾向', '基调', '氛围'],
            'content_category': ['类别', '类型', '种类', '分类', '归属'],
            'violence_level': ['暴力', '血腥', '激烈', '冲突', '危险'],
            'sensitive_content': ['敏感', '不当', '违规', '不适', '限制'],
            'target_audience': ['受众', '人群', '观众', '用户', '适用']
        }
        
        logger.info("提示词优化器初始化完成")
    
    def optimize_prompt(self, prompt: str, category: Optional[str] = None) -> str:
        """
        优化提示词
        
        Args:
            prompt: 需要优化的提示词
            category: 编码类目（可选）
            
        Returns:
            优化后的提示词
        """
        if not prompt:
            logger.warning("输入提示词为空，返回空字符串")
            return ""
        
        logger.info(f"开始优化提示词，原始长度: {len(prompt)} 字符")
        
        # 应用各种优化策略
        optimized_prompt = prompt
        
        # 1. 基础清理
        optimized_prompt = self._clean_prompt(optimized_prompt)
        
        # 2. 去除冗余
        optimized_prompt = self._remove_redundancy(optimized_prompt)
        
        # 3. 增强关键词（如果提供了类目）
        if category:
            optimized_prompt = self._enhance_keywords(optimized_prompt, category)
        
        # 4. 调整长度
        optimized_prompt = self._adjust_length(optimized_prompt)
        
        # 5. 改进清晰度
        optimized_prompt = self._improve_clarity(optimized_prompt)
        
        logger.info(f"提示词优化完成，优化后长度: {len(optimized_prompt)} 字符")
        return optimized_prompt
    
    def _clean_prompt(self, prompt: str) -> str:
        """
        基础清理：去除多余空格、换行符等
        
        Args:
            prompt: 原始提示词
            
        Returns:
            清理后的提示词
        """
        # 去除多余的空格
        cleaned = re.sub(r'\s+', ' ', prompt)
        
        # 确保段落间只有一个空行
        cleaned = re.sub(r'\n\s*\n\s*\n', '\n\n', cleaned)
        
        # 去除首尾空白
        cleaned = cleaned.strip()
        
        return cleaned
    
    def _remove_redundancy(self, prompt: str) -> str:
        """
        去除冗余短语和重复内容
        
        Args:
            prompt: 提示词
            
        Returns:
            去冗余后的提示词
        """
        optimized = prompt
        
        # 去除预定义的冗余短语
        for phrase in self.redundant_phrases:
            # 使用正则表达式进行替换，避免替换到单词中间的部分
            pattern = r'([\s，。！？；：])' + re.escape(phrase) + r'([\s，。！？；：])'
            optimized = re.sub(pattern, r'\1\2', optimized)
        
        # 去除连续重复的句子（简单版本）
        lines = optimized.split('\n')
        unique_lines = []
        for line in lines:
            if line.strip() and line.strip() not in unique_lines:
                unique_lines.append(line.strip())
        
        return '\n'.join(unique_lines)
    
    def _enhance_keywords(self, prompt: str, category: str) -> str:
        """
        根据编码类目增强相关关键词
        
        Args:
            prompt: 提示词
            category: 编码类目
            
        Returns:
            关键词增强后的提示词
        """
        if category not in self.category_keywords:
            logger.warning(f"未知的编码类目: {category}，跳过关键词增强")
            return prompt
        
        keywords = self.category_keywords[category]
        enhanced = prompt
        
        # 确保关键指令更加明确
        for keyword in keywords:
            # 这是一个简单的实现，可以根据需要扩展
            # 例如，可以添加更多的上下文增强逻辑
            pass
        
        # 对于主题类型，确保有明确的主题分析指令
        if category == 'theme_type' and '请分析视频的主题' not in enhanced:
            enhanced = enhanced.replace('请分析视频内容', '请分析视频内容和主题')
        
        # 对于情感倾向，确保有明确的情感分析指令
        elif category == 'emotional_tendency' and '请分析情感' not in enhanced:
            enhanced = enhanced.replace('请分析视频内容', '请分析视频内容和情感')
        
        return enhanced
    
    def _adjust_length(self, prompt: str) -> str:
        """
        调整提示词长度到合适范围
        
        Args:
            prompt: 提示词
            
        Returns:
            长度调整后的提示词
        """
        current_length = len(prompt)
        
        # 如果过长，进行精简
        if current_length > self.max_prompt_length:
            logger.warning(f"提示词过长，需要精简: {current_length} > {self.max_prompt_length}")
            return self._condense_prompt(prompt, self.max_prompt_length)
        
        # 如果过短，考虑是否需要补充
        elif current_length < self.min_prompt_length:
            logger.warning(f"提示词过短，可能需要补充: {current_length} < {self.min_prompt_length}")
            # 这里可以根据需要添加补充逻辑
        
        return prompt
    
    def _condense_prompt(self, prompt: str, max_length: int) -> str:
        """
        精简过长的提示词
        
        Args:
            prompt: 原始提示词
            max_length: 最大允许长度
            
        Returns:
            精简后的提示词
        """
        # 优先保留核心指令部分
        lines = prompt.split('\n')
        core_lines = []
        supplementary_lines = []
        
        for line in lines:
            if any(keyword in line for keyword in ['请分析', '确定', '回答', '输出']):
                core_lines.append(line)
            else:
                supplementary_lines.append(line)
        
        # 先组装核心部分
        condensed = '\n'.join(core_lines)
        
        # 然后尝试添加补充部分
        for line in supplementary_lines:
            if len(condensed) + len(line) + 1 <= max_length:  # +1 是换行符
                condensed += '\n' + line
            else:
                break
        
        # 如果还是太长，进行更激进的截断
        if len(condensed) > max_length:
            condensed = condensed[:max_length - 3] + '...'
        
        return condensed
    
    def _improve_clarity(self, prompt: str) -> str:
        """
        改进提示词的清晰度和明确性
        
        Args:
            prompt: 提示词
            
        Returns:
            清晰度改进后的提示词
        """
        improved = prompt
        
        # 确保使用明确的指令词
        clarity_replacements = {
            '请考虑': '请分析',
            '可能': '是',
            '或许': '是',
            '大概': '是',
            '尽量': '必须',
            '试着': '请'
        }
        
        for old, new in clarity_replacements.items():
            improved = improved.replace(old, new)
        
        # 确保指令明确且肯定
        if '请确保' not in improved:
            # 在提示词末尾添加明确要求
            if not improved.endswith(('。', '!', '！', '?', '？')):
                improved += '。'
            improved += ' 请确保回答准确且符合要求。'
        
        return improved
    
    def evaluate_prompt_quality(self, prompt: str, category: Optional[str] = None) -> Dict[str, float]:
        """
        评估提示词质量
        
        Args:
            prompt: 需要评估的提示词
            category: 编码类目（可选）
            
        Returns:
            包含各项质量指标的字典
        """
        metrics = {}
        
        # 1. 长度评分
        length = len(prompt)
        if self.min_prompt_length <= length <= self.max_prompt_length:
            metrics['length_score'] = 1.0
        elif length < self.min_prompt_length:
            metrics['length_score'] = min(0.8, length / self.min_prompt_length)
        else:
            metrics['length_score'] = max(0.6, 1.0 - (length - self.max_prompt_length) / self.max_prompt_length)
        
        # 2. 关键词覆盖率（如果提供了类目）
        if category and category in self.category_keywords:
            keywords = self.category_keywords[category]
            covered_count = sum(1 for keyword in keywords if keyword in prompt)
            metrics['keyword_coverage'] = covered_count / len(keywords)
        else:
            metrics['keyword_coverage'] = 0.5  # 默认值
        
        # 3. 指令明确性评分
        essential_instructions = ['请分析', '确定', '请确保', '输出']
        instruction_count = sum(1 for inst in essential_instructions if inst in prompt)
        metrics['instruction_clarity'] = min(1.0, instruction_count / 2)
        
        # 4. 整体质量评分（加权平均）
        metrics['overall_quality'] = (
            metrics['length_score'] * 0.3 +
            metrics['keyword_coverage'] * 0.4 +
            metrics['instruction_clarity'] * 0.3
        )
        
        logger.info(f"提示词质量评估完成: 整体质量={metrics['overall_quality']:.2f}")
        return metrics
    
    def batch_optimize(self, prompts: Dict[str, str]) -> Dict[str, str]:
        """
        批量优化提示词
        
        Args:
            prompts: 类目到提示词的映射
            
        Returns:
            优化后的提示词映射
        """
        optimized_prompts = {}
        
        for category, prompt in prompts.items():
            try:
                optimized = self.optimize_prompt(prompt, category)
                optimized_prompts[category] = optimized
                logger.info(f"类目 {category} 提示词优化完成")
            except Exception as e:
                logger.error(f"类目 {category} 提示词优化失败: {str(e)}")
                optimized_prompts[category] = prompt  # 使用原始提示词作为后备
        
        return optimized_prompts


# 单例模式访问函数
_prompt_optimizer_instance = None


def get_prompt_optimizer() -> PromptOptimizer:
    """
    获取提示词优化器的单例实例
    
    Returns:
        PromptOptimizer实例
    """
    global _prompt_optimizer_instance
    if _prompt_optimizer_instance is None:
        _prompt_optimizer_instance = PromptOptimizer()
    return _prompt_optimizer_instance


# 测试代码
if __name__ == "__main__":
    try:
        # 创建测试用的提示词
        test_prompt = """
        请分析视频内容，确定其主题类型。
        
        已知信息：场景设定: 校园场景
        
        视频中展示了校园环境，有学生、教室、黑板等元素。需要注意的是，你需要仔细分析视频的核心主题。
        请确保你的回答简洁明了，直接给出最符合视频内容的答案。
        """
        
        # 获取优化器实例
        optimizer = get_prompt_optimizer()
        
        # 测试优化功能
        print("原始提示词:")
        print(test_prompt)
        print(f"原始长度: {len(test_prompt)} 字符")
        print()
        
        # 优化提示词
        optimized = optimizer.optimize_prompt(test_prompt, 'theme_type')
        
        print("优化后的提示词:")
        print(optimized)
        print(f"优化后长度: {len(optimized)} 字符")
        print()
        
        # 评估质量
        metrics = optimizer.evaluate_prompt_quality(optimized, 'theme_type')
        print("质量评估结果:")
        for metric_name, score in metrics.items():
            print(f"{metric_name}: {score:.2f}")
        
    except Exception as e:
        logger.error(f"测试失败: {str(e)}")
        raise